
#include <string.h>
#include "drv_i2c.h"
#include "define.h"
#include <math.h>

BUS_DATA ipmi_data;
REPORT_DATA report_data;
/*-----------------------------------------------------------------------------
** PROC NAME	: i2cbus_thread_entry

** DESCRIPTION	: i2c slave receive data and handle

** PARAMETERS	: arg - i2c_periph I2Cx(x=0,1,2)

** RETURN       : 

** NOTES:
**----------------------------------------------------------------------------*/
static void send_report_data(uint32_t i2c_periph, uint8_t recv_addr, uint8_t *recv_buf, uint8_t report_data_value)
{
    int ret;
    report_data.reply[0] = report_data_value;
    report_data.reply[1] = 0x00;
    report_data.reply[2] = 0x00;
    report_data.check_sum = 0 - (ipmi_data.slave_add + recv_buf[3] + recv_buf[4] + 0x00 + report_data_value + 0x00 + 0x00);

    i2c_init_data(i2c_periph, I2C_MASTER_CH, recv_addr);
    ret = i2c_master_send(i2c_periph, recv_addr, (uint8_t *)&report_data, sizeof(report_data));
    if (ret)
    {
        rt_kprintf("%s: i2c_master_send error!\n", __func__);
    }
    i2c_init_data(i2c_periph, I2C_SLAVE_CH, ipmi_data.slave_add);
}

static void reply_sensor_data(uint8_t *recv_buf, uint32_t i2c_periph)
{
    int ret;
    float temp_raw = 0;
    float volt_raw = 0;
    float curr_raw = 0;
    uint8_t recv_addr = recv_buf[2];
    uint8_t sensor_id = recv_buf[5];
    char temp_str[10];

    sprintf(temp_str, "%d.%02d", ipmi_data.sensor_temp[0] / 100, (abs(ipmi_data.sensor_temp[0])) % 100);
    temp_raw = atof(temp_str);

    sprintf(temp_str, "%d.%02d", ipmi_data.sensor_V12V / 100, ipmi_data.sensor_V12V % 100);
    volt_raw = atof(temp_str);

    sprintf(temp_str, "%d.%02d", ipmi_data.sensor_I12V / 100, ipmi_data.sensor_I12V % 100);
    curr_raw = atof(temp_str);

	printf("temp_raw = %f, volt_raw = %f, curr_raw = %f\n", temp_raw, volt_raw, curr_raw); 

    report_data = (REPORT_DATA){
        .NetFn = recv_buf[0],
        .head_check_sum = 0 - (recv_buf[0] + recv_addr),
        .src_addr = ipmi_data.slave_add,
        .req_num = recv_buf[3],
        .cmd_code = recv_buf[4],
        .state = (temp_raw == 0 && volt_raw == 0 && curr_raw == 0) ? 0x01 : 0x00,// complete state(data ready?)
    };
    rt_kprintf("report_data.NetFn = 0x%x, report_data.head_check_sum = 0x%x\n,\
                report_data.src_addr = 0x%x, report_data.req_num = 0x%x\n,\
                report_data.cmd_code = 0x%x, report_data.state = 0x%x\n,\
                report_data.reply[0] = 0x%x, report_data.reply[1] = 0x%x\n,\
                report_data.reply[2] = 0x%x, report_data.check_sum = 0x%x\n",\
                report_data.NetFn, report_data.head_check_sum,\
                report_data.src_addr, report_data.req_num,\
                report_data.cmd_code, report_data.state,\
                report_data.reply[0], report_data.reply[1],\
                report_data.reply[2], report_data.check_sum);

    switch(sensor_id)
    {
        case SENSOR_NUM_TEMP:// temp
            send_report_data(i2c_periph, recv_addr, recv_buf,\
							SENSOR_CONVERT_RAW_VAL(temp_raw, SENSOR_TEMPO_M_MULTI_VAL, SENSOR_TEMPO_B_OFFSET_VAL,\
							SENSOR_TEMPO_K1_BEXP_VAL, SENSOR_TEMPO_K2_REXP_VAL));
            break;
        case SENSOR_NUM_12V_VOL:// voltage
            send_report_data(i2c_periph, recv_addr, recv_buf,\
							SENSOR_CONVERT_RAW_VAL(volt_raw, SENSOR_12V_M_MULTI_VAL, SENSOR_12V_B_OFFSET_VAL,\
							SENSOR_12V_K1_BEXP_VAL, SENSOR_12V_K2_REXP_VAL));
            break;
        case SENSOR_NUM_12V_CURR:// current
            send_report_data(i2c_periph, recv_addr, recv_buf,\
							SENSOR_CONVERT_RAW_VAL(curr_raw, SENSOR_12VA_M_MULTI_VAL, SENSOR_12VA_B_OFFSET_VAL,\
							SENSOR_12VA_K1_BEXP_VAL, SENSOR_12VA_K2_REXP_VAL));
            break;
		case SENSOR_NUM_FRU:// fru
			uint8_t fru_val = 0x10;
			send_report_data(i2c_periph, recv_addr, recv_buf, fru_val);
			break;
        default:
            rt_kprintf("recv invalid sensor number!\n");
            break;
    }
}

static void i2cbus_thread_entry(void *arg)
{
	uint32_t i2c_periph = (uint32_t) arg;
	rt_mq_t i2c_mq = (i2c_periph == I2C1) ? i2c1_mq : i2c0_mq;
	uint8_t buf[128];
	uint8_t i;
	
	while(1)
	{
		if(rt_mq_recv(i2c_mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
		{
			#if 1
			rt_kprintf("I2C%d recv: ", (i2c_periph == I2C1) ? 1 : 0);
			for(i=0; i<16; i++)
				rt_kprintf("%02x ", buf[i]);
			rt_kprintf("\n");
			#endif
			
			uint8_t cmd = buf[4];

			switch(cmd)
			{
				case 0x36:
					rt_kprintf("I2C%d recv: \n", (i2c_periph == I2C1) ? 1 : 0);
					rt_kprintf("I2C check is ok ! \n");
				break;

				case 0x20: // 读取设备传感器个数
					rt_kprintf("I2C%d recv: cmd = %02x\n", (i2c_periph == I2C1) ? 1 : 0, cmd);
				break;
				
				case 0x21: // 获取设备SDR
					rt_kprintf("I2C%d recv: cmd = %02x\n", (i2c_periph == I2C1) ? 1 : 0, cmd);
				break;
				
				case 0x22: // 获取设备SDR Reservation ID
					rt_kprintf("I2C%d recv: cmd = %02x\n", (i2c_periph == I2C1) ? 1 : 0, cmd);
				break;
				
				case 0x2d: // 读取传感器采样值
					rt_kprintf("I2C%d recv: cmd = %02x\n", (i2c_periph == I2C1) ? 1 : 0, cmd);
					reply_sensor_data(buf, i2c_periph);
				break;

				default:
					rt_kprintf("recv invalid cmd_type=%02x, drop!\n", buf[0]);
					continue;
			}
		}
	}
}

/*-----------------------------------------------------------------------------
** PROC NAME	: bus_start

** DESCRIPTION	: start i2c slave receive thread

** PARAMETERS	: i2c_periph - I2Cx(x=0,1,2)

** RETURN       : 0 - success, -1 - fail.

** NOTES:
**----------------------------------------------------------------------------*/
int bus_start(uint32_t i2c_periph)
{
	rt_thread_t tid;

	if(i2c_periph == I2C0)
	{
		i2c0_mq = rt_mq_create("i2c0mq", 128, 10, RT_IPC_FLAG_FIFO);
		if(i2c0_mq == RT_NULL)
		{
			rt_kprintf("rt_mq_create() failed.\n");
		}
		
		tid = rt_thread_create("i2c0_ip", i2cbus_thread_entry, (void *)I2C0,4096, 4, 20);
		if (tid != RT_NULL)
		{
			rt_thread_startup(tid);
		}
		
		i2c_reset_rx_data(i2c_periph);	
		
		/* enable the I2Cx interrupt */
		i2c_interrupt_enable(i2c_periph, I2C_INT_ERR);
		i2c_interrupt_enable(i2c_periph, I2C_INT_EV);
		i2c_interrupt_enable(i2c_periph, I2C_INT_BUF);
	}
		
	if(i2c_periph == I2C1)
	{
		i2c1_mq = rt_mq_create("i2c1mq", 128, 10, RT_IPC_FLAG_FIFO);
		if(i2c1_mq == RT_NULL)
		{
			rt_kprintf("rt_mq_create() failed.\n");
		}
		
		tid = rt_thread_create("i2c1_ip", i2cbus_thread_entry, (void *)I2C1,4096, 5, 20);
		if (tid != RT_NULL)
		{
			rt_thread_startup(tid);
		}
		
		i2c_reset_rx_data(i2c_periph);	
		
		/* enable the I2Cx interrupt */
		i2c_interrupt_enable(i2c_periph, I2C_INT_ERR);
		i2c_interrupt_enable(i2c_periph, I2C_INT_EV);
		i2c_interrupt_enable(i2c_periph, I2C_INT_BUF);
	}	

	return 0;
}

